package org.jeecg.modules.zhima.portal.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import org.jeecg.modules.zhima.admin.entity.ZmPayOrder;
import org.jeecg.modules.zhima.admin.service.IZmPayOrderService;
import org.jeecg.modules.zhima.base.common.ResultCode;
import org.jeecg.modules.zhima.base.exception.Asserts;
import org.jeecg.modules.zhima.base.shiro.service.TokenService;
import org.jeecg.modules.zhima.base.util.BigDecimalUtils;
import org.jeecg.modules.zhima.base.util.RedisUtil;
import org.jeecg.modules.zhima.center.entity.OmsOrder;
import org.jeecg.modules.zhima.center.entity.SmsCouponHistory;
import org.jeecg.modules.zhima.center.entity.UmsMember;
import org.jeecg.modules.zhima.center.enums.OrderStatus;
import org.jeecg.modules.zhima.center.enums.PayStatus;
import org.jeecg.modules.zhima.center.service.IOmsOrderService;
import org.jeecg.modules.zhima.center.service.ISmsCouponHistoryService;
import org.jeecg.modules.zhima.pay.bean.WxTrade;
import org.jeecg.modules.zhima.pay.bean.common.Trade;
import org.jeecg.modules.zhima.pay.bean.common.TradeToken;
import org.jeecg.modules.zhima.portal.domain.OrderPrepayReturn;
import org.jeecg.modules.zhima.portal.service.IPayOrderService;
import org.jeecg.modules.zhima.portal.service.IPayService;
import org.jeecg.modules.zhima.portal.service.IUserService;
import org.jeecg.modules.zhima.portal.weixin.TradeManager;
import org.jeecg.modules.zhima.portal.weixin.WechatService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Slf4j
@Service
public class PayServiceImpl implements IPayService {
    @Autowired
    private IUserService userService;
    @Autowired
    private IOmsOrderService omsOrderService;
    @Autowired
    private WechatService wechatService;
    @Autowired
    private ISmsCouponHistoryService couponHistoryService;
    @Autowired
    private TradeManager tradeManager;
    @Autowired
    private IZmPayOrderService zmPayOrderService;
    @Autowired
    private IPayOrderService payOrderService;
    @Autowired
    private RedisUtil redisService;
    @Value("${redis.key.orderId}")
    private String REDIS_KEY_ORDER_ID;
    @Value("${redis.database}")
    private String REDIS_DATABASE;
    @Autowired
    private TokenService tokenService;


    @Override
    public OrderPrepayReturn prepay(Integer orderId) {

        UmsMember member = userService.getCurrentMember();
        if (member == null){
            Asserts.fail(ResultCode.UNAUTHORIZED);
        }
        OmsOrder order = omsOrderService.getById(orderId);
        if (order == null){
            Asserts.fail("无效订单");
        }
        //修改优惠券状态
        if (ObjectUtils.isNotEmpty(order.getCouponId()) && order.getCouponId() > 0){
            SmsCouponHistory history = couponHistoryService.getById(order.getCouponId());
            history.setUseStatus(1);
            history.setUpdateTime(new Date());
            couponHistoryService.updateById(history);
        }
        OrderPrepayReturn prepayReturn = null;
        try {
            prepayReturn = wechatService.unifiedOrder(order.getOrderSn(), BigDecimalUtils.multiply(order.getPayAmount(), 100).intValue(), member.getWeixinOpenid());
        } catch (WxPayException e) {
            e.printStackTrace();
        }
        return prepayReturn;
    }

    @Override
    public WxPayOrderNotifyResult payNotify(HttpServletRequest request) throws WxPayException, IOException {
        String xmlResult = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
        WxPayOrderNotifyResult result = wechatService.parseOrderNotifyResult(xmlResult);
        String type = result.getAttach();
        if (StringUtils.isNotBlank(type) && type.equals("1")){
            // 加入自己处理订单的业务逻辑，需要判断订单是否已经支付过，否则可能会重复调用
            String orderSn = result.getOutTradeNo();
            String tradeNo = result.getTransactionId();
            String totalFee = BaseWxPayResult.fenToYuan(result.getTotalFee());
            log.info("payNotify: orderSn={}, tradeNo={}, totalFee={}, result={}", orderSn, tradeNo, totalFee, JSON.toJSONString(result));
            payOrderService.payCallback(orderSn);
            return result;
        }else if (StringUtils.isNotBlank(type) && type.equals("2")){
            // 加入自己处理订单的业务逻辑，需要判断订单是否已经支付过，否则可能会重复调用
            String orderSn = result.getOutTradeNo();
            String tradeNo = result.getTransactionId();
            String totalFee = BaseWxPayResult.fenToYuan(result.getTotalFee());
            log.info("payNotify: orderSn={}, tradeNo={}, totalFee={}, result={}", orderSn, tradeNo, totalFee, JSON.toJSONString(result));
            OmsOrder order = omsOrderService.getByOrderSn(orderSn);
            if (order != null && (order.getStatus().equals(OrderStatus.WAIT_PAY.CODE))){
                omsOrderService.onPaySuccess(order);
            }
            return result;
        }
        return null;
    }

    @Override
    public List<OmsOrder> checkAllPayStatus(Integer memberId) {
        return wechatService.checkPayStatus(omsOrderService.list(memberId, OrderStatus.WAIT_PAY.CODE));
    }

    @Override
    public OmsOrder checkPayStatus(Integer orderId) {
        List<OmsOrder> list = new ArrayList<>();
        list.add(omsOrderService.getById(orderId));
        list = wechatService.checkPayStatus(list);
        return list.get(0);
    }

    @Override
    public void qrcodePay() {
        Trade trade = WxTrade
//                .webMobilePay()
                .qrcodePay()
                .body("商品标题")
                .outTradeNo("test"+System.currentTimeMillis())
                .totalFee("1")
                .spbillCreateIp("127.0.0.1")
                .sceneInfo("商品测试场景")
                .notifyUrl("http://xxxx")
                .build();
//        TradeToken<String> token = tradeManager.webMobilePay(trade);
//        TradeToken<String> token = tradeManager.jsSdkPay(trade);
        TradeToken<String> token = tradeManager.qrcodePay(trade);
        String url = token.value();
        log.info("pay res == {}", JSON.toJSONString(token));
    }

    @Override
    public void refund(String outTradeNo, String totalFee) {
        Trade trade = WxTrade.jsSdkPay()
                .outTradeNo(outTradeNo)
                .totalFee(totalFee)
                .build();
        tradeManager.refund(trade);
    }

    @Override
    public OrderPrepayReturn createJoinOrder(BigDecimal payment, String gamePlayerId) {
        UmsMember member = tokenService.getLoginUser();
        if (member == null){
            Asserts.fail(ResultCode.UNAUTHORIZED);
        }
        ZmPayOrder zmPayOrder = payOrderService.getByGamePlayerId(gamePlayerId);
        if (zmPayOrder == null){
            zmPayOrder = new ZmPayOrder();
            zmPayOrder.setCreateTime(new Date());
            zmPayOrder.setStatus(PayStatus.WAIT_PAY.CODE);
            zmPayOrder.setPayAmount(payment);
            zmPayOrder.setGamePlayerId(gamePlayerId);
            zmPayOrder.setType(1);
            zmPayOrder.setOrderSn(generateOrderSn(zmPayOrder));
            zmPayOrderService.save(zmPayOrder);
        }
        OrderPrepayReturn prepayReturn = null;
        try {
//            prepayReturn = wechatService.unifiedOrder(zmPayOrder.getOrderSn(), BigDecimalUtils.multiply(payment, 100).intValue(), member.getWeixinOpenid());
            //TODO 支付付款金额 测试金额1分
//            prepayReturn = wechatService.unifiedOrder(zmPayOrder.getOrderSn(), 1, member.getWeixinOpenid());
            prepayReturn = wechatService.unifiedOrder(zmPayOrder.getOrderSn(), payment.multiply(new BigDecimal(100)).intValue(), member.getWeixinOpenid());
        } catch (WxPayException e) {
            e.printStackTrace();
        }
        return prepayReturn;
    }

    /**
     * 生成18位订单编号:8位日期+2位平台号码+2位支付方式+6位以上自增id
     */
    private String generateOrderSn(ZmPayOrder payOrder) {
        StringBuilder sb = new StringBuilder();
        String date = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
        String key = REDIS_DATABASE+":"+ REDIS_KEY_ORDER_ID + date;
        Long increment = redisService.incr(key, 1);
        sb.append(date);
        sb.append(String.format("%02d", payOrder.getType()));
        String incrementStr = increment.toString();
        if (incrementStr.length() <= 6) {
            sb.append(String.format("%06d", increment));
        } else {
            sb.append(incrementStr);
        }
        return sb.toString();
    }
}
